package com.zz.common.protocol.handle;

import com.zz.common.entity.Meta;
import com.zz.common.protocol.DefaultProtocol;
import com.zz.common.protocol.TunnelProtocol;
import com.zz.common.serialize.SerializeFactory;
import com.zz.common.utils.ObjectUtil;
import com.zz.common.utils.SnowflakeUtil;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;

import java.nio.charset.StandardCharsets;

import static com.zz.common.config.Constants.Numbers.*;

/**
 * 默认消息协议编解码器
 *
 * @author zz
 */
public class DefaultProtocolHandle implements ProtocolHandle {


    @Override
    public void encode(ChannelHandlerContext context, TunnelProtocol protocol, ByteBuf byteBuf) {
        DefaultProtocol defaultProtocol = (DefaultProtocol) protocol;
        // 计算消息体总字节长度
        int bodyLength = TYPE_SIZE + SERIAL_NUMBER_SIZE + HEADER_LENGTH_SIZE + SERIALIZE_SIDE + META_SIZE;
        if (ObjectUtil.isNotEmpty(defaultProtocol.getHeader())) {
            bodyLength += defaultProtocol.getHeader().length();
        }
        if (ObjectUtil.isNotEmpty(defaultProtocol.getData())) {
            bodyLength += defaultProtocol.getData().length;
        }
        byte[] meta = new byte[0];
        if (ObjectUtil.isNotEmpty(defaultProtocol.getMeta())) {
            // 序列化元数据信息
            meta = SerializeFactory.getInstances(defaultProtocol.getSerializationType())
                                                    .serialize(defaultProtocol.getSerializationType(), defaultProtocol.getMeta());
            bodyLength += meta.length;
        }
        // 写入消息头（消息体总长度）
        byteBuf.writeInt(bodyLength);
        // 写入消息类型和消息序列号
        byteBuf.writeByte(defaultProtocol.getType());
        byteBuf.writeLong(getSerialNumber(defaultProtocol.getSerialNumber()));
        // 如果 header 体不为空 则写入 header 长度和 header 内容
        if (ObjectUtil.isNotEmpty(defaultProtocol.getHeader())) {
            byte[] headerByte = defaultProtocol.getHeader().getBytes(StandardCharsets.UTF_8);
            byteBuf.writeByte((byte) headerByte.length);
            byteBuf.writeBytes(headerByte);
        } else {
            byteBuf.writeByte(ZERO);
        }
        // 写入序列化方式
        byteBuf.writeByte(defaultProtocol.getSerializationType());
        byteBuf.writeInt(meta.length);
        if (ObjectUtil.isNotEmpty(meta)) {
            byteBuf.writeBytes(meta);
        }
        if (ObjectUtil.isNotEmpty(defaultProtocol.getData())) {
            byteBuf.writeBytes(defaultProtocol.getData());
        }
    }

    private long getSerialNumber(long serialNumber) {
        if (serialNumber == 0) {
            return SnowflakeUtil.genSnowflakeId();
        }
        return serialNumber;
    }

    @Override
    public TunnelProtocol decode(ChannelHandlerContext context, ByteBuf byteBuf) {
        // 协议总长度
        int frameLength = byteBuf.readInt();
        if (byteBuf.readableBytes() < frameLength) {
            return null;
        }
        DefaultProtocol protocol = new DefaultProtocol();
        // 消息类型
        protocol.setType(byteBuf.readByte());
        // 消息唯一标识
        protocol.setSerialNumber(byteBuf.readLong());
        // 消息头
        byte headerLen = byteBuf.readByte();
        if (headerLen > 0) {
            byte[] headerData = new byte[headerLen];
            byteBuf.readBytes(headerData);
            protocol.setHeader(new String(headerData));
        }
        // 序列化协议
        byte serializeType = byteBuf.readByte();
        // 元数据
        int mataLen = byteBuf.readInt();
        if (mataLen > 0) {
            byte[] metaByte = new byte[mataLen];
            byteBuf.readBytes(metaByte);
            Meta meta = SerializeFactory.getInstances(serializeType).deserialize(serializeType, metaByte, Meta.class);
            protocol.setMeta(meta);
        }
        byte[] dataByte = new byte[frameLength - TYPE_SIZE - SERIAL_NUMBER_SIZE - HEADER_LENGTH_SIZE - SERIALIZE_SIDE - META_SIZE - headerLen - mataLen];
        byteBuf.readBytes(dataByte);
        protocol.setData(dataByte);
        return protocol;
    }
}
